function whatType(obj) {
  return Object.prototype.toString.call(obj)
}

function isType(...objs) {
  return (
    objs.map(item => whatType(item) === whatType(objs[0])).filter(item => !item)
      .length === 0
  )
}

function isObject(...objs) {
  return isType(...objs, {})
}

function isArray(...objs) {
  return isType(...objs, [])
}

function isOb(...objs) {
  return objs.every(obj => inType(obj, [{}, []]))
}

function isBoolean(...objs) {
  return isType(...objs, true)
}

function isString(...objs) {
  return isType(...objs, '')
}

function isNumber(...objs) {
  return isType(...objs, 1) && !isNaN(...objs)
}

function isSymbol(...objs) {
  return isType(...objs, Symbol('Symbol'))
}

function isPromise(...objs) {
  return isType(...objs, Promise.resolve())
}

function isNaN(...objs) {
  return objs.every(obj => Number.isNaN(obj))
}

function isNull(...objs) {
  return isType(...objs, null)
}

function isUndef(...objs) {
  return isType(...objs, undefined)
}

function isReg(...objs) {
  return isType(...objs, /d/)
}

function isNil(...objs) {
  return objs.every(obj => inType(obj, [undefined, null]))
}

function isFunc(...objs) {
  return objs.every(obj => inType(obj, [() => {}, async () => {}]))
}

function inType(params, list) {
  if (!isType(list, [])) {
    throw new Error(`list expect a ${whatType([])}`)
  }
  let flag = false
  for (const i in list) {
    if (isType(list[i], params)) {
      flag = true
      break
    }
  }
  return flag
}

function removeEmpty(obj) {
  if (!isObject(obj)) throw new Error('expected a object')

  const result = {}
  for (const key in obj) {
    const val = obj[key]
    if (isNil(val)) {
      continue
    }

    if (isArray(val) && val.length === 0) {
      continue
    }

    if (val === false) {
      continue
    }

    result[key] = val
  }

  return result
}

module.exports = {
  whatType,
  inType,
  isArray,
  isBoolean,
  isFunc,
  isNaN,
  isNil,
  isNumber,
  isString,
  isSymbol,
  isUndef,
  isObject,
  isOb,
  isNull,
  isPromise,
  isReg,
  removeEmpty
}
